//
//  main.swift
//  PerfectTemplate
//
//  Created by Kyle Jessup on 2015-11-05.
//	Copyright (C) 2015 PerfectlySoft, Inc.
//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Perfect.org open source project
//
// Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors
// Licensed under Apache License v2.0
//
// See http://perfect.org/licensing.html for license information
//
//===----------------------------------------------------------------------===//
//
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import PerfectSession
import PerfectSessionSQLite
import SQLiteStORM
import TurnstileCrypto
import PerfectMustache
import PerfectMarkdown
import PerfectRequestLogger
import PerfectWebSockets
// An example request handler.
// This 'handler' function can be referenced directly in the configuration below.
func handler(data: [String:Any]) throws -> RequestHandler {
	return {
		request, response in
		// Respond with a simple message.
		response.setHeader(.contentType, value: "application/json")
        let port = request.remoteAddress.port
        let ip = request.remoteAddress.host
        let documentRoot = request.documentRoot
        let serverName = request.serverName
        let parame = request.queryParams
        let uri = request.uri
        var head :[Any] = [Any]()
        for item in request.headers {
            head.append(item)
        }
        let cookie = request.cookies
        let dic :[String:Any] = ["客户端连接端口":port,"客户端连接IP":ip,"服务器的文档根目录":documentRoot,"服务器名称":serverName,"客户端参数":parame,"客户端的uri":uri,"请求头参数":head,"Cookie":cookie]
        print(dic)
        let json = ["name":"小明","age":12,"性别":true] as [String : Any]
        do{
            try response.setBody(json: json)
        }catch{
        
        }
        
		// Ensure that response.completed() is called when your processing is done.
		response.completed()
	}
}

//post响应参数
func postHandler(data:[String:Any])throws -> RequestHandler {
    return{
    request,response in
        let paramer = request.postParams
        print(paramer)
        //response.status = HTTPResponseStatus.custom(code: 1000, message: "给你开个玩笑")
        response.setHeader(HTTPResponseHeader.Name.custom(name: "plateform"), value: "weixin")
        response.push(callback: { (isComplete) in
            print(isComplete)
        })
        
        ///设置流媒体模式
        ///最大的区别就是响应内容长度未知
        response.isStreaming = true
        response.completed()
    }
}
//文件上传
func uploadHandler()throws -> RequestHandler {
    return{
        request,response in

        response.completed()
    }
}


// Configuration data for two example servers.
// This example configuration shows how to launch one or more servers 
// using a configuration dictionary.

let port1 = 8080, port2 = 8181
let header = "<html><head><link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\"><title>Perfect Sessions Demo</title><style>.header,body{padding-bottom:20px}.header,.jumbotron{border-bottom:1px solid #e5e5e5}body{padding-top:20px}.footer,.header,.marketing{padding-right:15px;padding-left:15px}.header h3{margin-top:0;margin-bottom:0;line-height:40px}.footer{padding-top:19px;color:#777;border-top:1px solid #e5e5e5}@media (min-width:768px){.container{max-width:730px}}.container-narrow>hr{margin:30px 0}.jumbotron{text-align:center}.jumbotron .btn{padding:14px 24px;font-size:21px}.marketing{margin:40px 0}.marketing p+h4{margin-top:28px}@media screen and (min-width:768px){.footer,.header,.marketing{padding-right:0;padding-left:0}.header{margin-bottom:30px}.jumbotron{border-bottom:0}}</style></head><body><div class=\"container\"><div class=\"header clearfix\"><h3 class=\"text-muted\"><a href=\"/\">Perfect Sessions Demo</a></h3></div>"

let footer = "</div></body></html>"

let confData = [
	"servers": [
		// Configuration data for one server which:
		//	* Serves the hello world message at <host>:<port>/
		//	* Serves static files out of the "./webroot"
		//		directory (which must be located in the current working directory).
		//	* Performs content compression on outgoing data when appropriate.
		[
			"name":"localhost",
			"port":port1,
			"routes":[
				["method":"get", "uri":"/", "handler":handler],
				["method":"get", "uri":"/**", "handler":PerfectHTTPServer.HTTPHandler.staticFiles,
				 "documentRoot":"./webroot",
				 "allowResponseFilters":true],
                ["method":"post","uri":"/addItem","handler":postHandler]
			],
			"filters":[
				[
				"type":"response",
				"priority":"high",
				"name":PerfectHTTPServer.HTTPFilter.contentCompression,
				]
			]
		],
		// Configuration data for another server which:
		//	* Redirects all traffic back to the first server.
		[
			"name":"localhost",
			"port":port2,
			"routes":[
				["method":"get", "uri":"/**", "handler":PerfectHTTPServer.HTTPHandler.redirect,
				 "base":"http://localhost:\(port1)"],
			]
		]
	]
]















//MARK:路由
var routes = Routes()
routes.add(method: .post, uri: "/") { (request, response) in
   let params = request.params()
    StaticFileHandler(documentRoot: request.documentRoot).handleRequest(request: request, response: response)
    print("响应句柄:\(params)")
    response.setHeader(HTTPResponseHeader.Name.custom(name: "platform"), value: "ios")
    let json:[[String:Any]] = [
        [
        "name":"小红",
        "age":15,
        "school":"清华大学",
        "sex":false
        ],
        [
        "name":"小明",
        "age":17,
        "school":"北京大学",
        "sex":true
        ]
                        ]
    do{
        try response.setBody(json: json)
    }catch{
        fatalError("\(error)")
    }
    response.completed()
}
routes.add(method: .get, uri: "/session") { (request, response) in
    let rand = URandom()
    request.session.data[rand.secureToken] = rand.secureToken
    
    var dump = ""
    do{
        dump = try request.session.data.jsonEncodedString()
    }catch{
        dump = "\(error)"
    }
    
    var body = "<p>Your Session ID is: <code>\(request.session.token)</code></p><p>Session data: <code>\(dump)</code></p><p>your userid :<code> \(request.session.userid)</code></p>"
    body += "<p><a href=\"/withcsrf\">CSRF Test Form</a></p>"
    body += "<p><a href=\"/nocsrf\">No CSRF Test Form</a></p>"
    
    response.setBody(string: header+body+footer)
    response.completed()
}


//静态文件
routes.add(method: .get, uri: "/documentRoot/**") { (request, response) in
    print(request.documentRoot)
    print(request.header(HTTPRequestHeader.Name.custom(name: "platform")) ?? "111")
    print(request.path)
    
    request.path = request.urlVariables[routeTrailingWildcardKey]!
    
    print(request.path)
    let handler = StaticFileHandler(documentRoot: "/var/www/htdocs")
    handler.handleRequest(request: request, response: response)
    
    response.completed()
}


//MARK:Mustache 服务器用法
struct MustAcheHandle:MustachePageHandler {
    func extendValuesForResponse(context contxt: MustacheWebEvaluationContext, collector: MustacheEvaluationOutputCollector) {
        var values = MustacheEvaluationContext.MapType()
        values["value"] = "您好"
        contxt.extendValues(with: values)
        do{
            try contxt.requestCompleted(withCollector: collector)
        }catch{
            let response = contxt.webResponse
            response.status = .internalServerError
            response.appendBody(string: "\(error)")
            response.completed()
        }
    }
}
routes.add(method: .get, uri: "/mustache") { (request, response) in
    //这里进行服务器请求重定向
    mustacheRequest(request: request, response: response, handler: MustAcheHandle(), templatePath: "/test.html")
}

routes.add([webSocket()])

BytesTransform()

rocumentFile()

dir()

promiseDemo()

createUUID()
//Mustache 独立使用(非服务器用法)
let templateText = "TOP {\n{{#name}}\n{{name}}{{/name}}\n}\nBOTTOM"
let d = ["name":"The name"] as [String:Any]
let contxt = MustacheEvaluationContext(templateContent: templateText, map: d)
let collector = MustacheEvaluationOutputCollector()
let responseString = try contxt.formulateResponse(withCollector: collector)
print("Mustache:\(responseString)")

//MARK:Markdown 生成HTML的方法
routes.add(method: .get, uri: "/markdown") { (request, response) in
    let markdown = "# This is markdown document \n\n## with mojo China\n"
    let html = markdown.markdownToHTML
    print(html ?? "markdown转换HTML失败")
    response.setBody(string: html!)
    response.completed()
}

//MARK:过滤器
struct requestFilter:HTTPRequestFilter{     //请求过滤器
    func filter(request: HTTPRequest, response: HTTPResponse, callback: (HTTPRequestFilterResult) -> ()) {
        let params = request.params()
        print("请求过滤器:\(params)")
        callback(.continue(request, response))
    }
}
struct responseFilter:HTTPResponseFilter {      //响应过滤器
    func filterHeaders(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
        print("响应过滤器请求头:\(response.header(HTTPResponseHeader.Name.custom(name: "platform")) ?? "没有响应头")")
        callback(.continue)
    }
    func filterBody(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
//        let b = response.bodyBytes
//        print("响应过滤器请求体\(b)")
        callback(.done)
    }
}
//404响应过滤器
struct Filter404:HTTPResponseFilter{
    func filterHeaders(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
        if case .notFound = response.status {
            response.setBody(string: "文件\(response.request.path)不存在")
            response.setHeader(.contentLength, value: "\(response.bodyBytes.count)")
            callback(.done)
        }else{
            callback(.continue)
        }
    }
    func filterBody(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
        callback(.continue)
    }
}


//MARK:Session会话
SessionConfig.name = "TestingSQLiteDrivers"     //会话名称
SessionConfig.idle = 86400                      //许处于零活动连接的时间限制，单位是秒

SessionConfig.cookieDomain = "localhost"        //可选项，设置 Cookie作用域
SessionConfig.IPAddressLock = true              //IP锁定,ID发生变化会话失败
SessionConfig.userAgentLock = true              //协议锁定,协议发生变化会话失败

SQLiteConnector.db = "./SessionDB"              //指定采用SQLite作为内存管理后台,指定SQLite内用于管理会话的数据库名称

let sessionDriver = SessionSQLiteDriver()       //会话驱动


//MARK:JSON编解码
//JSON编码
let soreArr:[String:Any] = ["第一名": 300, "第二名": 230.45, "第三名": 150]
let encoded = try soreArr.jsonEncodedString()
print("json编码:\(encoded)")

//JSON解码
let encode = "{\"第二名\":230.45,\"第一名\":300,\"第三名\":150,\"第四名\":null}"
let decode = try encode.jsonDecode()
print("json解码:\(decode)")

//MARK:注册对象
class User:JSONConvertibleObject{
    static let registeName = "user"
    var firstName = ""
    var lastName = ""
    var age = 0
    //解码的时候调用
    override func setJSONValues(_ values: [String : Any]) {
        self.firstName = getJSONValue(named: "firstName", from: values, defaultValue: "")
        self.lastName = getJSONValue(named: "lastName", from: values, defaultValue: "")
        self.age = getJSONValue(named: "age", from: values, defaultValue: 0)
    }
    //编码的时候调用
    override func getJSONValues() -> [String : Any] {
        return[
            JSONDecoding.objectIdentifierKey:User.registeName,
            "firstName":firstName,
            "lastName":lastName,
            "age":age
        ]
    }
}
JSONDecoding.registerJSONDecodable(name: User.registeName) { () -> JSONConvertibleObject in
    return User()
}
let user = User()
user.firstName = "Donnie"
user.lastName = "Darko"
user.age = 17
let userEncode = try user.jsonEncodedString()
print("User对象编码:\(userEncode)")
let user2 = try userEncode.jsonDecode() as! User
print("User对象解码:\(user2.firstName)  \(user2.lastName)  \(user2.age)")

let server = HTTPServer()
let requestFilters:[(HTTPRequestFilter,HTTPFilterPriority)] = [(requestFilter(),HTTPFilterPriority.high),sessionDriver.requestFilter]
let responseFilters:[(HTTPResponseFilter,HTTPFilterPriority)] = [(responseFilter(),HTTPFilterPriority.high),(Filter404(),HTTPFilterPriority.high),sessionDriver.responseFilter]
server.serverPort = UInt16(port2)
server.serverName = "localhost"
server.addRoutes(routes)
server.setRequestFilters(requestFilters)
server.setResponseFilters(responseFilters)

//MARK:http请求日志记录
let  myLogger = RequestLogger()
server.setRequestFilters([(myLogger, .high)])
server.setResponseFilters([(myLogger,.low)])


do{
    try server.start()
}catch{
    fatalError("\(error)")
}







